Write Your Own CVs and Methods¶
One of the basic design goals of SSAGES is that it should be easily extensible. To this end, it provides intuitive and simple tools to implement new collective variables (CVs) and new advanced sampling methods. This section covers the basic steps to implement a new CV or a new Method. Let us first start with the implementation of a new CV. The techniques to implement a new Method are covered below.
How to Write a New CV¶
Each CV consists of two components: a header file and a schema file. The header file contains the source code for the calculation of the CV and the schema file describes the properties of the CV in a simple JSON format. Finally, you will have to make SSAGES aware of the new CV by incorporating it into the core classes.
The CV Header File¶
Each CV in SSAGES is implemented as a child of the class CollectiveVariable
.
The header file should be placed in the directory src/CVs/
and has to
(re)implement the following functions:
void Initialize(const Snapshot&)
(optional)Called during the pre-simulation phase. It is typically used to allocate or reserve memory.
void Evaluate(const Snapshot&)
Evaluation of the CV based on a simulation snapshot. This function should calculate both the value and gradient of the CV. The gradient should be a vector of length \(n\), where \(n\) is the number of atoms in the Snapshot. Each element in the vector is the derivative of the CV with respect to the corresponding atom’s coordinates. This method is called in the post-integration phase of every iteration.
double GetValue() const
Return the current value of the CV, as calculated in
Evaluate(const Snapshot&)
.double GetPeriodicValue() const
Return the current value of the CV, taking periodic boundary conditions into account. An example would be an angular CV which is bound to the region \((-\pi,\pi]\). In this case,
GetValue()
could return any angle, whileGetPeriodicValue()
should return the angle mapped back into the region \((-\pi,\pi]\). If the CV does not use periodic boundaries, this function should return the same value asGetValue()
.const std::vector<Vector3>& GetGradient() const
Return the gradient of the CV (see
Evaluate(const Snapshot&)
for how the gradient is defined).const std::array<double, 2>& GetBoundaries() const
Return a two-element array containing the lower and the upper boundary for the CV.
double GetDifference(double Location) const
Return the distance of the current value of the CV from a specified location, taking periodic boundary conditions into account. If the CV does not use periodic boundary conditions, the return value should simply be
GetValue() - Location
.
The CV Schema File¶
Together with the header file that contains the source code of the CV, you will
have to provide a schema file to make the CV accessible to the SSAGES input
files. The schema file should be placed in the directory schema/CVs/
. It
has to be written in the JSON format and should contain the following items:
- type
The value of
type
should be set toobject
.- varname
The name of your new CV, of the form
ExampleCV
.- properties
The properties contain the
type
which is the internal name of the CV and a set of other properties that have to be supplied to the constructor of the CV.- required
A list containing the required properties. Optional parameters to the CV constructor are not listed here.
- additionalProperties
A boolean value allowing unlisted JSON members to be included in input files.
Integrate the New CV into SSAGES¶
Once you have provided the header and schema files, there are two more steps in order to make SSAGES aware of the newly included CV.
To include your new CV, you have to edit the file
src/CVs/CollectiveVariable.cpp
, and
#include
your CV header file at the top of the file.Add a new
else if
clause inBuildCV()
. The if-test checks for the type of CV selected and returns the respectiveBuild(json, path)
function from the new CV.
How to Write a New Method¶
Each method consists of three components: a header file (.h
),
a source file (.cpp
), and a schema file (.json
).
The header and source files contain the main code for the method
and the schema file describes the properties of the method in a simple JSON
format. Finally, you will have to make SSAGES aware of the new method by
incorporating it into the core classes.
The Method Header File¶
Each method in SSAGES is implemented as a child of the class Methods
.
The header file should be placed in the directory src/Methods
and has to
declare the following functions:
void PreSimulation(Snapshot* snapshot, const CVList& cvs)
Called before the method actually runs. It is typically used to allocate or reserve memory.
void PostIntegration(Snapshot* snapshot, const CVList& cvs)
Called after each MD integration step. This is where the heart of your method should go. By using Snapshot and the CVs, this function modifies the forces, positions, velocities, etc. appropriated by the new method.
void PostSimulation(Snapshot* snapshot, const CVList& cvs)
Called at the end of the simulation run. Use it to close files your method opened, to write out data that the method is storing, etc.
void Build
Called upon instantiation of SSAGES to build your method. Standard parts include reading the JSON input and setting variables.
Any other variables or functions that your new method will need to use must be declared here (or defined, if simple enough).
The Method Source File¶
The source file should be placed in the directory src/Methods
and has to
(re)implement the functions defined above: PreSimulation()
,
PostIntegration()
, PostSimulation
, and Build()
. Any functions
that were declared in the header file need to be defined, as well.
For String Method variants, edit the logic framework in
src/Methods/StringMethod.cpp
for the Build()
function, instead of
your new source file.
The Method Schema File¶
Together with the source code of the method, you will
have to provide a schema file to make the method accessible to the SSAGES input
files. The schema file should be placed in the directory schema/Methods/
. It
has to be written in the JSON format and should contain the following items:
- type
The value of
type
should be set toobject
.- varname
The name of your new method, of the form
ExampleMethod
.- properties
The properties contain the
type
which is the internal name of the method and a set of other properties that have to be supplied to the constructor of the method.- required
A list containing the required properties. Optional parameters to the method constructor are not listed here.
- additionalProperties
A boolean value allowing unlisted JSON members to be included in input files.
If your new method uses the String Method framework, you simply need to add a
new “flavor” of this method, defined in schema/Methods/string.method.json
.
Integrate the New Method into SSAGES¶
Once you have provided the header, source, and schema files, there are two more steps in order to make SSAGES aware of the newly included method.
To include your new method, you have to edit the file
src/Methods/Method.cpp
, and
#include
your method header file at the top of the file.Add a new
else if
clause inBuildMethod()
. The if-test checks for the type of method selected and calls the respectiveBuild(json, world, comm, path)
function from the new method. A pointer to the newly created object should be stored in the variable namedmethod
.
Finally, add the method .cpp
file to CMakeLists.txt as a source.